home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / The Hacks / Airport Radar™ / Source / BaseStation.cp next >
Encoding:
Text File  |  2001-06-23  |  10.3 KB  |  406 lines

  1. /*
  2.     File:         BaseStation.c
  3.  
  4.     Contains:    Class to handle a base station
  5.  
  6.     Version:    MacHack 2001
  7. */
  8.  
  9. #include "BaseStation.h"
  10.  
  11. #include <stdio.h>
  12. #include <math.h>
  13.  
  14. struct BaseLocation
  15. {
  16.     UInt16                            fMACAddress[3];
  17.     UInt32                            fX;
  18.     UInt32                            fY;
  19.     const char*                        fName;
  20. };
  21.  
  22.  
  23. BaseLocation    sBaseLocations[] = {
  24.                                         {    0x0060, 0x1D1E, 0x3703, 357,    211,    "Balcony"},
  25.                                         {    0x0060, 0x1D1E, 0xE6AE, 376,    91,        "Machine Room"},
  26.                                         {    0x0060, 0x1DF6, 0x8C27, 47,        623,    "Sicily"},
  27.                                         {    0x0060, 0x1DF0, 0x0E49, 395,    661,    "Hotel Desk"},
  28.                                         {    0x0060, 0x1D1E, 0x324E, 672,    97,     "C&G Far"},
  29.                                         {    0x0060, 0x1DF0, 0x0B26, 555,    26,     "C&G Middle"}
  30.                                     };
  31.  
  32. // ---------------------------------------------------------------------------
  33. //    BaseStation
  34. // ---------------------------------------------------------------------------
  35.  
  36. BaseStation::BaseStation()
  37. {
  38.     fSignal = 0.0;
  39.     fSignalAverage = 0.0;
  40.     fNoise = 0.0;
  41.     
  42.     fMACAddress[0] = 0;
  43.     fMACAddress[1] = 0;
  44.     fMACAddress[2] = 0;
  45.  
  46.     fX = 0.0;
  47.     fY = 0.0;
  48.     
  49.     fR = 0.0;
  50.     
  51.     fName = "";
  52. }
  53.  
  54. // ---------------------------------------------------------------------------
  55. //    ~BaseStation
  56. // ---------------------------------------------------------------------------
  57.  
  58. BaseStation::~BaseStation()
  59. {
  60. }
  61.  
  62. // ---------------------------------------------------------------------------
  63. //    UpdateInfo
  64. // ---------------------------------------------------------------------------
  65.  
  66. void BaseStation::UpdateInfo(WirelessNodeInfoPtr inBaseInfo)
  67. {
  68.     fSignal = inBaseInfo->fSignalLevel;
  69.     fSignalAverage = (fSignalAverage + fSignal) / 2.0;
  70.     fNoise = inBaseInfo->fNoiseLevel;
  71.  
  72.     fMACAddress[0] = inBaseInfo->fMACAddress[0];
  73.     fMACAddress[1] = inBaseInfo->fMACAddress[1];
  74.     fMACAddress[2] = inBaseInfo->fMACAddress[2];
  75. }
  76.  
  77.  
  78. // ---------------------------------------------------------------------------
  79. //    BaseStationList
  80. // ---------------------------------------------------------------------------
  81.  
  82. BaseStationList::BaseStationList()
  83. {
  84.     OSStatus                error = noErr;
  85.  
  86.     fBaseCount = 0;
  87.     fRef = 0;
  88.     
  89.     fX = 0.0;
  90.     fY = 0.0;
  91.     
  92.     error = WirelessConnect(&fRef, 0);
  93. }
  94.  
  95. // ---------------------------------------------------------------------------
  96. //    ~BaseStationList
  97. // ---------------------------------------------------------------------------
  98.  
  99. BaseStationList::~BaseStationList()
  100. {
  101.     if (fRef)
  102.     {
  103.         WirelessDisconnect(fRef);
  104.     }
  105. }
  106.  
  107.  
  108. // ---------------------------------------------------------------------------
  109. //    CalcDistanceSquared
  110. // ---------------------------------------------------------------------------
  111.  
  112. double
  113. BaseStationList::CalcDistanceSquared(
  114.     const SectPoint &        inPoint1,
  115.     const SectPoint &        inPoint2)
  116. {
  117.     double        xDiff = inPoint1.fX - inPoint2.fX;
  118.     double        yDiff = inPoint1.fY - inPoint2.fY;
  119.     return xDiff * xDiff + yDiff * yDiff;
  120. }
  121.  
  122.  
  123. // ---------------------------------------------------------------------------
  124. //    FindMostLikelyLocation
  125. // ---------------------------------------------------------------------------
  126.  
  127. void
  128. BaseStationList::FindMostLikelyLocation(
  129.     const SectPoints *        inSectPoint,
  130.     UInt32                    inSectPointCount)
  131. {
  132.     // Among each of the intersection pairs, one of the
  133.     // points is correct. We can guess which one is correct
  134.     // by triangulation (i.e. comparing the points to find
  135.     // "similar" points).
  136.     
  137.     double totalDiff1 = 0.0;
  138.     double totalDiff2 = 0.0;
  139.     SectPoint xyTotal1 = inSectPoint[0].fPoint1;
  140.     SectPoint xyTotal2 = inSectPoint[0].fPoint2;
  141.     
  142.     for (UInt32 i = 1; i < inSectPointCount; i++)
  143.     {
  144.         double        diff1;
  145.         double        diff2;
  146.         
  147.         diff1 = CalcDistanceSquared(inSectPoint[0].fPoint1, inSectPoint[i].fPoint1);
  148.         diff2 = CalcDistanceSquared(inSectPoint[0].fPoint1, inSectPoint[i].fPoint2);
  149.         
  150.         // Is point1[0] closer to point1[i] or point2[i]?
  151.         if (diff1 < diff2)
  152.         {
  153.             totalDiff1 += diff1;
  154.             xyTotal1.fX += inSectPoint[i].fPoint1.fX;
  155.             xyTotal1.fY += inSectPoint[i].fPoint1.fY;
  156.         }
  157.         else
  158.         {
  159.             totalDiff1 += diff2;
  160.             xyTotal1.fX += inSectPoint[i].fPoint2.fX;
  161.             xyTotal1.fY += inSectPoint[i].fPoint2.fY;
  162.         }
  163.  
  164.         diff1 = CalcDistanceSquared(inSectPoint[0].fPoint2, inSectPoint[i].fPoint1);
  165.         diff2 = CalcDistanceSquared(inSectPoint[0].fPoint2, inSectPoint[i].fPoint2);
  166.         
  167.         // Is point2[0] closer to point1[i] or point2[i]?
  168.         if (diff1 < diff2)
  169.         {
  170.             totalDiff1 += diff1;
  171.             xyTotal2.fX += inSectPoint[i].fPoint1.fX;
  172.             xyTotal2.fY += inSectPoint[i].fPoint1.fY;
  173.         }
  174.         else
  175.         {
  176.             totalDiff1 += diff2;
  177.             xyTotal2.fX += inSectPoint[i].fPoint2.fX;
  178.             xyTotal2.fY += inSectPoint[i].fPoint2.fY;
  179.         }
  180.     }
  181.     
  182.     if (totalDiff1 < totalDiff2)
  183.     {
  184.         fX = xyTotal1.fX / inSectPointCount;
  185.         fY = xyTotal1.fY / inSectPointCount;
  186.     }
  187.     else
  188.     {
  189.         fX = xyTotal2.fX / inSectPointCount;
  190.         fY = xyTotal2.fY / inSectPointCount;
  191.     }
  192. }
  193.  
  194.  
  195. // ---------------------------------------------------------------------------
  196. //    FindIntersectionPoints
  197. // ---------------------------------------------------------------------------
  198.  
  199. void
  200. BaseStationList::FindIntersectionPoints(
  201.     BaseStation *        inBase1,
  202.     BaseStation *        inBase2,
  203.     SectPoints &        outSectPoint)
  204. {
  205.     double        xDiff = inBase2->fX - inBase1->fX;
  206.     double        yDiff = inBase2->fY - inBase1->fY;
  207.     double        distance = sqrt(xDiff * xDiff + yDiff * yDiff);
  208.     
  209.     outSectPoint.fBaseStation1 = inBase1;
  210.     outSectPoint.fBaseStation2 = inBase2;
  211.  
  212.     double scaleFactor = inBase1->fR / (inBase1->fR + inBase2->fR);
  213.     SectPoint    scaledCenter;
  214.     scaledCenter.fX = inBase1->fX + xDiff * scaleFactor;
  215.     scaledCenter.fY = inBase1->fY + yDiff * scaleFactor;
  216.     
  217.     // If the two don't intersect, we have to assume that
  218.     // the location is between the two.
  219.     if (distance >= inBase1->fR + inBase2->fR)
  220.     {
  221.         outSectPoint.fPoint1 = scaledCenter;
  222.         outSectPoint.fPoint2 = scaledCenter;
  223.     }
  224.     else
  225.     {
  226.         // Calculate the distance from the middle of circle one 
  227.         // to the center of the chord.
  228.         double chordX = inBase1->fX - scaledCenter.fX;
  229.         double chordY = inBase1->fY - scaledCenter.fY;
  230.         double distanceToChordSq = chordX * chordX + chordY * chordY;
  231.         
  232.         // Calculate how far along the chord in each direction we
  233.         // need to travel to get to the circle.
  234.         double distanceAlongChordSq = inBase1->fR * inBase1->fR - distanceToChordSq;
  235.         
  236.         // Determine the slope of the chord (which is the inverse of the
  237.         // slope of the line from the center of the circle to the chord).
  238.         double slopeOfChord = chordX / chordY;
  239.         
  240.         // Solve the following equations:
  241.         // x^2 + y^2 = d^2        d = distance along chord
  242.         // y / x = m            m = slope
  243.         // y = xm
  244.         // x^2 + x^2m^2 = d^2
  245.         // x = sqrt(d^2 / (1 + m^2))
  246.         double chordXDiff = sqrt(distanceAlongChordSq / (1 + slopeOfChord * slopeOfChord));
  247.         
  248.         outSectPoint.fPoint1.fX = scaledCenter.fX + chordXDiff;
  249.         outSectPoint.fPoint2.fX = scaledCenter.fX - chordXDiff;
  250.         outSectPoint.fPoint1.fY = scaledCenter.fY - chordXDiff * slopeOfChord;
  251.         outSectPoint.fPoint2.fY = scaledCenter.fY + chordXDiff * slopeOfChord;
  252.     }
  253. }
  254.  
  255.  
  256. // ---------------------------------------------------------------------------
  257. //    AddBase
  258. // ---------------------------------------------------------------------------
  259.  
  260. void BaseStationList::AddBase(WirelessNodeInfoPtr inBaseInfo)
  261. {
  262.     UInt32    index;
  263.     Boolean found = false;
  264.     
  265.     for (index = 0; index < fBaseCount; index++)
  266.     {
  267.         if ((fBases[index].fMACAddress[0] == inBaseInfo->fMACAddress[0]) &&
  268.             (fBases[index].fMACAddress[1] == inBaseInfo->fMACAddress[1]) &&
  269.             (fBases[index].fMACAddress[2] == inBaseInfo->fMACAddress[2]))
  270.         {
  271.             found = true;
  272.             break;
  273.         }
  274.     }
  275.     
  276.     if (found == false)
  277.     {
  278.         index = fBaseCount;
  279.         fBaseCount++;
  280.         
  281.         fBases[index].UpdateInfo(inBaseInfo);
  282.         
  283.         for (UInt32    locIndex = 0; locIndex < (sizeof(sBaseLocations)/sizeof(BaseLocation)); locIndex++)
  284.         {
  285.             if ((fBases[index].fMACAddress[0] == sBaseLocations[locIndex].fMACAddress[0]) &&
  286.                 (fBases[index].fMACAddress[1] == sBaseLocations[locIndex].fMACAddress[1]) &&
  287.                 (fBases[index].fMACAddress[2] == sBaseLocations[locIndex].fMACAddress[2]))
  288.             {
  289.                 fBases[index].fX = sBaseLocations[locIndex].fX;
  290.                 fBases[index].fY = sBaseLocations[locIndex].fY;
  291.                 
  292.                 fBases[index].fName = sBaseLocations[locIndex].fName;
  293.                 
  294.                 found = true;
  295.                 break;
  296.             }
  297.         }
  298.     }
  299.     else
  300.     {
  301.         fBases[index].UpdateInfo(inBaseInfo);
  302.     }
  303. }
  304.  
  305.  
  306. // ---------------------------------------------------------------------------
  307. //    IdleBases
  308. // ---------------------------------------------------------------------------
  309.  
  310. void BaseStationList::IdleBases(void)
  311. {
  312.     OSStatus                error = noErr;
  313.     WirelessNodeInfo        nodes[256];
  314.     SInt32                    nodeCount;
  315.     
  316.     nodeCount = 256;
  317.     
  318.     error = WirelessScanMerge(fRef, nodes, &nodeCount, 2, 1);
  319.     
  320.     while(nodeCount--)
  321.     {
  322.         AddBase(&(nodes[nodeCount]));
  323.     }
  324.     
  325.     MapMyLocation();
  326. }
  327.  
  328.  
  329. // ---------------------------------------------------------------------------
  330. //    MapMyLocation
  331. // ---------------------------------------------------------------------------
  332.  
  333. void BaseStationList::MapMyLocation(void)
  334. {
  335.     //    r = -19.73(s) +    1918.5
  336.     UInt32            index;
  337.     UInt32            triIndex;
  338.     BaseStation *    baseTriangle[3];
  339.     
  340.     // Scale the values
  341.     for (index = 0; index < fBaseCount; index++)
  342.     {
  343.         fBases[index].fStrongSignal = false;
  344.         
  345.         //    Made this shit up
  346.         fBases[index].fR = (-19.73 * fBases[index].fSignalAverage) + 1918.5;
  347.         
  348.         fBases[index].fR = fBases[index].fR / 2.0;        //    3.5;
  349.         
  350.         if (fBases[index].fR < 0.01)
  351.             fBases[index].fR = 0.01;
  352.     }
  353.     
  354.     baseTriangle[0] = nil;
  355.     baseTriangle[1] = nil;
  356.     baseTriangle[2] = nil;
  357.     
  358.     // We can't triangulate unless we can see at least two base stations.
  359.     if (fBaseCount > 2)
  360.     {
  361.         // Find the three base stations that have the strongest signals.
  362.         // Lame sort
  363.         for (index = 0; index < fBaseCount; index++)
  364.         {
  365.             for (triIndex = 0; triIndex < 3; triIndex++)
  366.             {
  367.                 if (baseTriangle[triIndex])
  368.                 {
  369.                     if (baseTriangle[triIndex]->fSignalAverage < fBases[index].fSignalAverage)
  370.                     {
  371.                         for (UInt32 shiftIndex = 2; shiftIndex > triIndex; shiftIndex--)
  372.                         {
  373.                             baseTriangle[shiftIndex] = baseTriangle[shiftIndex-1];
  374.                         }
  375.                         
  376.                         baseTriangle[triIndex] = &fBases[index];
  377.                         break;
  378.                     }
  379.                 }
  380.                 else
  381.                 {
  382.                     baseTriangle[triIndex] = &fBases[index];
  383.                     break;
  384.                 }
  385.             }
  386.         }
  387.  
  388.         baseTriangle[0]->fStrongSignal = true;
  389.         baseTriangle[1]->fStrongSignal = true;
  390.         baseTriangle[2]->fStrongSignal = true;
  391.         
  392.         // Find the six points that represent the intersection 
  393.         // points of the two circles.
  394.         FindIntersectionPoints(baseTriangle[0], baseTriangle[1], fSectPoints[0]);
  395.         FindIntersectionPoints(baseTriangle[1], baseTriangle[2], fSectPoints[1]);
  396.         FindIntersectionPoints(baseTriangle[0], baseTriangle[2], fSectPoints[2]);
  397.  
  398.         FindMostLikelyLocation(fSectPoints, 3);
  399.     }
  400.     else
  401.     {
  402.         // fix me - handle just two base stations?
  403.     }
  404. }
  405.  
  406.